﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FunctionGraph
{
    public abstract class ExpressionNode
    {
        public abstract T Accept<T>(ExpressionVisitor<T> visitor);
    }

    public class ConstantNode : ExpressionNode
    {
        public double Value;

        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitConstant(this);
        }
    }

    public class VariableNode : ExpressionNode
    {
        public string VariableName;

        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitVariable(this);
        }
    }

    public enum MathOperator
    {
        Illegal,
        Add, Sub, Mul, Div, Mod,
        Pow, Pow1, Eql, Neq, Leq, Geq, Less, Greater,
        And, Or, Not, Neg,
        Sin,
        Cos,
        Abs,
        Floor,
        Ceil
    }

    public class BinaryNode : ExpressionNode
    {
        public ExpressionNode Left, Right;
        public MathOperator Operator;

        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitBinary(this);
        }
    }

    public class UnaryNode : ExpressionNode
    {
        public ExpressionNode Child;
        public MathOperator Operator;

        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitUnary(this);
        }
    }


    public abstract class SolutionEvaluationNode : ExpressionNode
    {
    }

    public class BinarySolutionEvaluationNode : SolutionEvaluationNode
    {
        public MathOperator Operator;
        public SolutionEvaluationNode Left, Right;
        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitBinarySolutionEval(this);
        }
    }

    public class ExprSolutionEvaluationNode : SolutionEvaluationNode
    {
        public Executable ExprExecutable;
        public int EvaluatorId;
        public override T Accept<T>(ExpressionVisitor<T> visitor)
        {
            return visitor.VisitExprSolutionEvaluationNode(this);
        }
    }

}
